fix: correctness hardening — force-kill ownership check, sync cwd validation, lock/parse robustness#21
Merged
Conversation
…ck/parse robustness Three small correctness fixes batched: up --force (#5): the port sweep kill -9'd whatever lsof found listening on the session's recorded ports — stale ports meant killing another session's service or an unrelated app. PIDs now go through whose_pid::resolve scoped to this session; unowned listeners get a warning instead of a SIGKILL, owned ones get TERM with a 2s grace before KILL. The sweep runs before the pid-file kill so ownership can still be established from the pid files. ecluse sync (#8): the cwd fallback accepted any directory whose path contained the slug as a substring (and any cwd under the repo root, including the main checkout). It now requires the cwd to be inside a linked git worktree of this repo and uses that worktree's root. robustness (#11): acquire_shared returned an empty state when state.lock was missing even though state.json existed (and had a panic path); it now recreates the lock file and reads the real state. ls no longer panics on a short started_at. .env.ecluse parsing is unified in env::parse_env_file — shell, env, up --json, and process spawning read the file identically, and comment lines no longer leak into JSON output as keys. Fixes #5 Fixes #8 Fixes #11 https://claude.ai/code/session_017UcuvzMKHVfyBCcq8ipAko
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5
Fixes #8
Fixes #11
Three small correctness fixes, batched because each is a focused few-line change.
up --force: ownership check + graceful kill (#5)The port sweep
kill -9'd whateverlsoffound listening on the session's recorded ports. A stale recorded port (rebooted machine, auto-bump elsewhere, unrelated app) meant killing an innocent process — while the project shipswhose-pidspecifically to stop agents doing the same thing.lsofis resolved viawhose_pid::resolvescoped to this session; unowned listeners produce a warning ("kill it manually if intended") and are skippedSIGTERMwith a 2s grace, thenSIGKILL— no more immediate-9Behavior change to be aware of:
--forceno longer kills a manually-started, untracked process squatting the session's port — it warns instead. That is the point of #5, and the warning says exactly what to do.ecluse sync: real worktree check instead of substring match (#8)The cwd fallback accepted any directory whose path string contained the slug (
/home/me/rapid-prototypematches slugapi), plus any cwd under the repo root — including the main checkout, which sync would happily register as a session worktree. The fallback now requires the cwd to be inside a linked git worktree of this repo (is_inside_git_worktree+main_worktree_root == root, canonicalized) and uses that worktree's actual root.Robustness batch (#11)
acquire_sharedreturned an empty state whenstate.lockwas missing even thoughstate.jsonexisted with live sessions (lssaid "no active sessions" while everything ran), and had an.expectpanic path. It now creates the dir + lock file the same wayacquiredoes and reads the real state.lsno longer panics on a short/hand-editedstarted_at([..16]byte-slice →.get(..16)fallback)..env.eclusehad four divergent parsers (shellskipped comments,env/up --jsondidn't — comment lines leaked into JSON as keys,process.rshad a fourth variant). One sharedenv::parse_env_filenow backs all of them.Tests
acquire_shared_reads_state_when_lock_file_missing(fails on the old empty-state behavior)parse_env_file_*: comments/blanks skipped, first-=split, missing-file empty, file order preservedsync_rejects_repo_root_as_worktreecargo fmt --check,cargo clippy -- -D warnings,cargo test(374 + 19) green.https://claude.ai/code/session_017UcuvzMKHVfyBCcq8ipAko
Generated by Claude Code